package com.css.fxfzdzzh.modules.basicData.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.PageUtil;
import com.alibaba.fastjson.JSONObject;
import com.css.fxfzdzzh.base.annotation.EntityValue;
import com.css.fxfzdzzh.base.annotation.Transform;
import com.css.fxfzdzzh.base.attachment.entity.AttachmentInfoEntity;
import com.css.fxfzdzzh.base.attachment.service.AttachmentInfoService;
import com.css.fxfzdzzh.base.dict.repository.DictItemRepository;
import com.css.fxfzdzzh.base.dict.repository.DictRepository;
import com.css.fxfzdzzh.base.dict.repository.entity.DictEntity;
import com.css.fxfzdzzh.base.dict.repository.entity.DictItemEntity;
import com.css.fxfzdzzh.base.exception.StrategyFactoryException;
import com.css.fxfzdzzh.base.response.RestResponse;
import com.css.fxfzdzzh.constants.FxfzConstants;
import com.css.fxfzdzzh.constants.RedisKeyConstants;
import com.css.fxfzdzzh.constants.YNEnum;
import com.css.fxfzdzzh.modules.basicData.entity.*;
import com.css.fxfzdzzh.modules.basicData.landslideSite.entity.FieldDesc;
import com.css.fxfzdzzh.modules.basicData.param.PageQueryParam;
import com.css.fxfzdzzh.modules.basicData.param.SysDataVersionSameTypeDataExistParam;
import com.css.fxfzdzzh.modules.basicData.param.SysDataVersionSaveMetaDataInfoParam;
import com.css.fxfzdzzh.modules.basicData.param.sysDataVersion.SysDataVersionPageParam;
import com.css.fxfzdzzh.modules.basicData.repository.impl.SeismotectionRepository;
import com.css.fxfzdzzh.modules.basicData.repository.impl.SysDataVersionRepository;
import com.css.fxfzdzzh.modules.basicData.vo.DictItemTreeNodeVo;
import com.css.fxfzdzzh.modules.basicData.vo.SysDataVersionFileVO;
import com.css.fxfzdzzh.modules.basicData.vo.SysDataVersionGetByVersionCodeVo;
import com.css.fxfzdzzh.modules.basicData.vo.VersionVO;
import com.css.fxfzdzzh.modules.basicData.vo.sysDataVersion.SysDataVersionPageVo;
import com.css.fxfzdzzh.util.*;
import com.css.fxfzdzzh.util.fileParsing.ParsingResult;
import com.css.fxfzdzzh.util.fileParsing.shp.ShpAnalyticUtil;
import com.css.fxfzdzzh.web.PlatformSessionContext;
import com.css.fxfzdzzh.zcpt.sys.entity.SUser;
import com.css.fxfzdzzh.zcpt.sys.service.SUserService;
import com.css.fxfzdzzh.zcpt.sys.service.SysAreaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Dbj
 * @date 2023年02月25日  14:06
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class SysDataVersionService {

    @Value("${image.localDir}")
    private String localDir;

    @Resource
    SysAreaService sysAreaService;

    @Resource
    SUserService sUserService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    SysDataVersionRepository sysDataVersionRepository;

    @Resource
    private LandformService landformService;

    @Resource
    AttachmentInfoService attachmentInfoService;

    @Resource
    NaturalDensityService naturalDensityService;

    @Resource
    SensingImageService sensingImageService;

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    SeismotectionService seismotectionService;

    @Resource
    DictRepository dictRepository;

    @Resource
    DictItemRepository dictItemRepository;

    /**
     * 保存新版本
     *
     * @param sysDataVersion
     */
    @Transactional(rollbackFor = Exception.class)
    public String saveNewVersion(SysDataVersion sysDataVersion) {
        //判断是否生成过版本信息
        SysDataVersion dbSysDataVersion = sysDataVersionRepository.selectOneByType2(sysDataVersion.getDataTypeLevel1Code(), sysDataVersion.getDataTypeLevel2());
        if (PlatformObjectUtils.isNotEmpty(dbSysDataVersion)) {
            String versionCode = dbSysDataVersion.getVersionCode();
            //删除上个版本上传的数据信息
            this.deleteUploadData(versionCode, dbSysDataVersion.getDataTypeLevel2());
        }
        String userJson = sUserService.getSUser(sysDataVersion.getUploadUser());
        SUser sUser = CreateGson.createGson().fromJson(userJson, SUser.class);
        sysDataVersion.setVersionCode(getVersionCode(sysDataVersion));
        sysDataVersion.setId(IdUtil.simpleUUID());
        sysDataVersion.setDelFlag(YNEnum.N.toString());
        sysDataVersion.setUploadTime(new Date());
        sysDataVersion.setUploadUser(sUser.getUserId());
        sysDataVersion.setUploadUserName(sUser.getUserName());
        sysDataVersion.setCreateTime(new Date());
        sysDataVersion.setCreateUser(sysDataVersion.getUploadUser());
        sysDataVersion.setIsSpatialData(Integer.parseInt(YNEnum.Y.toString()));
        //占位符
        sysDataVersion.setDataTypeLevel3("");
        StringBuilder areaId = new StringBuilder("");
        if (PlatformObjectUtils.isNotEmpty(sysDataVersion.getDataRangeProvince()) && !"全国".equals(sysDataVersion.getDataRangeProvince())) {
            areaId.append(sysDataVersion.getDataRangeProvince());
        }
        if (PlatformObjectUtils.isNotEmpty(sysDataVersion.getDataRangeCity()) && !"全部".equals(sysDataVersion.getDataRangeCity())) {
            areaId.append(",").append(sysDataVersion.getDataRangeCity());
        }
        if (PlatformObjectUtils.isNotEmpty(sysDataVersion.getDataRangeArea()) && !"全部".equals(sysDataVersion.getDataRangeArea())) {
            areaId.append(",").append(sysDataVersion.getDataRangeArea());
        }
        String areaName = "";
        if (StringUtils.isNotBlank(areaId.toString())) {
            areaName = sysAreaService.getAreaNameByAreaId(areaId.toString());
        }
        sysDataVersion.setDataRangeStr(getDataRanageStr(areaName, sysDataVersion.getDataRangeCountry()));
        //保存版本数据信息
        sysDataVersionRepository.save(sysDataVersion);
        //替换临时版本号并生效解析的数据
        updateByVersion(sysDataVersion);
        //返回真实的版本号
        return sysDataVersion.getVersionCode();
    }

    /**
     * 替换临时版本号并生效解析的数据
     */
    private void updateByVersion(SysDataVersion sysDataVersion) {
        String dataTypeLevel1Code = sysDataVersion.getDataTypeLevel1Code();
        if (dataTypeLevel1Code.equals(FxfzConstants.LANDSLIDE)) {
            //滑坡遥感影像
            sensingImageService.updateByLsVersion(sysDataVersion.getTempVersionCode(), sysDataVersion.getVersionCode(), sysDataVersion.getDataRangeCountry());
        }
        if (dataTypeLevel1Code.equals(FxfzConstants.LANDFORM)) {
            //地貌
            landformService.updateByVersion(sysDataVersion.getTempVersionCode(), sysDataVersion.getVersionCode(), sysDataVersion.getDataRangeCountry());
        }
        if (dataTypeLevel1Code.equals(FxfzConstants.NATUREDENSITY)) {
            //天然密度
            naturalDensityService.updateByVersion(sysDataVersion.getTempVersionCode(), sysDataVersion.getVersionCode(), sysDataVersion.getDataRangeCountry());
        }
        if (dataTypeLevel1Code.equals(FxfzConstants.SEISMOTECTONIS)) {
            String dataTypeLevel2 = sysDataVersion.getDataTypeLevel2();
            if (FxfzConstants.BELT.equals(dataTypeLevel2)) {
                //地震构造带
                seismotectionService.updateBeltByVersion(sysDataVersion.getTempVersionCode(), sysDataVersion.getVersionCode());
            } else if (FxfzConstants.ZONE.equals(dataTypeLevel2)) {
                //地震构造区
                seismotectionService.updateZoneByVersion(sysDataVersion.getTempVersionCode(), sysDataVersion.getVersionCode());
            }

        }
    }


    //保存版本数据信息
    private String getDataRanageStr(String areaName, Integer dataRangeCountry) {
        StringBuilder dataRanageStr = new StringBuilder("");
        if (dataRangeCountry == 1) {
            dataRanageStr.append("国家级");
        } else {
            dataRanageStr.append("省级");
        }
        if (!"".equals(areaName)) {
            String[] split = areaName.split(",");
            if (split.length == 1) {
                dataRanageStr.append("(").append(split[0]).append(")");
            } else if (split.length == 2) {
                if (areaName.split(",")[0].equals(split[1])) {
                    dataRanageStr.append("(").append(split[0]).append(")");
                } else {
                    dataRanageStr.append("(").append(split[0]).append(split[1]).append(")");
                }
            } else {
                if (split[0].equals(split[1])) {
                    dataRanageStr.append("(").append(split[0]).append(split[2]).append(")");
                } else {
                    dataRanageStr.append("(").append(split[0]).append(split[1]).append(split[2]).append(")");
                }
            }
        }
        return dataRanageStr.toString();
    }

    /**
     * 删除之前版本上传的数据
     */
    private void deleteUploadData(String versionCode, String dataTypeLevel2) {
        switch (dataTypeLevel2) {
            case FxfzConstants.HPYGYX:
                sensingImageService.deleteByVersion(versionCode);
                break;
            case FxfzConstants.DM:
                landformService.deleteByVersion(versionCode);
                break;
            case FxfzConstants.TRMD:
                naturalDensityService.deleteByVersion(versionCode);
                break;
            case FxfzConstants.BELT:
                seismotectionService.deleteBeltByVersion(versionCode);
                break;
            case FxfzConstants.ZONE:
                seismotectionService.deleteZoneByVersion(versionCode);
                break;
            default:
                break;
        }
    }

    private String getVersionCode(SysDataVersion sysDataVersion) {
        return this.getVersionCode(sysDataVersion.getDataRangeCountry());
    }

    public synchronized String getVersionCode(@NotNull Integer sjfw) {
        String dataVersionCodeSerialNumber = stringRedisTemplate.opsForValue().get(RedisKeyConstants.DATA_VERSION_CODE_SERIAL_NUMBER_KEY);
        if (StringUtils.isBlank(dataVersionCodeSerialNumber)) {
            dataVersionCodeSerialNumber = "001";
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            String t = String.valueOf(Integer.parseInt(dataVersionCodeSerialNumber) + 1);
            for (int i = t.length(); i < 3; i++) {
                stringBuilder.append("0");
            }
            dataVersionCodeSerialNumber = stringBuilder.append(t).toString();
        }
        stringRedisTemplate.opsForValue().set(RedisKeyConstants.DATA_VERSION_CODE_SERIAL_NUMBER_KEY, dataVersionCodeSerialNumber);
        stringRedisTemplate.expireAt(RedisKeyConstants.DATA_VERSION_CODE_SERIAL_NUMBER_KEY, Date.from(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).toInstant(ZoneOffset.of("+8"))));
        return "YW0" + sjfw + "GZQS" + DateUtil.format(new Date(), "yyyyMMdd") + dataVersionCodeSerialNumber;
    }

    public List<String> getVersionCodeListByType(Map<String, Object> map) {
        return sysDataVersionRepository.getVersionCodeListByType(map);
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveMetaDataInfo(SysDataVersionSaveMetaDataInfoParam param) {
        param.setUpdateTime(new Date());
        param.setUpdateUser(PlatformSessionContext.getUserID());
        sysDataVersionRepository.saveMetaDataInfo(param);
    }

    public SysDataVersionGetByVersionCodeVo getMetaDataByVersionCode(String versionCode) {
        SysDataVersion sysDataVersion = sysDataVersionRepository.getByVersionCode(versionCode);
        Integer fieldEntry = sysDataVersion.getFieldEntry();
        String dataTypeLevel2 = sysDataVersion.getDataTypeLevel2();
        if (PlatformObjectUtils.isEmpty(fieldEntry)) {
            if (dataTypeLevel2.equals(FxfzConstants.HPYGYX)) {
                fieldEntry = sensingImageService.getValidDataNum(versionCode);
            }
            if (dataTypeLevel2.equals(FxfzConstants.DM)) {
                fieldEntry = landformService.getValidDataNum(versionCode);
            }
            if (dataTypeLevel2.equals(FxfzConstants.TRMD)) {
                fieldEntry = naturalDensityService.getValidDataNum(versionCode);
            }
            if (dataTypeLevel2.equals(FxfzConstants.BELT)) {
                fieldEntry = seismotectionService.getBeltValidDataNum(versionCode);
            }
            if (dataTypeLevel2.equals(FxfzConstants.ZONE)) {
                fieldEntry = seismotectionService.getZoneValidDataNum(versionCode);
            }
        }
        Integer fieldNum = sysDataVersion.getFieldNum();
        if (PlatformObjectUtils.isEmpty(fieldNum)) {
            List<FieldDesc> list = new ArrayList<>();
            if (dataTypeLevel2.equals(FxfzConstants.HPYGYX)) {
                list = sensingImageService.getFieldDesc();
            }
            //地貌业务数据
            if (dataTypeLevel2.equals(FxfzConstants.DM)) {
                list = landformService.getFieldDesc();
            }
            //天然密度数据
            if (dataTypeLevel2.equals(FxfzConstants.TRMD)) {
                list = naturalDensityService.getFieldDesc();
            }
            //地震构造-地震带
            if (dataTypeLevel2.equals(FxfzConstants.BELT)) {
                list = seismotectionService.getBeltFieldDesc();
            }
            //地震构造-地震构造区
            if (dataTypeLevel2.equals(FxfzConstants.ZONE)) {
                list = seismotectionService.getZoneFieldDesc();
            }
            fieldNum = list.size();
        }
        String json = sUserService.getSUser(PlatformSessionContext.getUserID());
        SUser sUser = CreateGson.createGson().fromJson(json, SUser.class);
        SysDataVersionGetByVersionCodeVo build = SysDataVersionGetByVersionCodeVo.builder()
                .versionCode(versionCode)
                .uploadTime(sysDataVersion.getUploadTime())
                .uploadSource(sysDataVersion.getUploadSource())
                .dataRangeCountry(sysDataVersion.getDataRangeCountry())
                .dataRangeProvince(sysDataVersion.getDataRangeProvince())
                .dataRangeCity(sysDataVersion.getDataRangeCity())
                .dataRangeArea(sysDataVersion.getDataRangeArea())
                .isSpatialData(1)
                .spatialDataType(3)
                .projectionInfo(sysDataVersion.getProjectionInfo())
                .fieldNum(fieldNum)
                .fieldEntry(fieldEntry)
                .coordinateSystemType("大地坐标系")
                .coordinateSystemName("2000国家大地坐标系")
                .coordinateSystemEnName("CGCS2000")
                .uploadUser(sysDataVersion.getUploadUser())
                .build();
        if (build != null) {
            build.setUploadUser(sUser.getUserName());
        }
        return build;
    }

    @Transactional(rollbackFor = Exception.class)
    public String overwriteOldVersion(SysDataVersion sysDataVersion) throws Exception{
        String userJson = sUserService.getSUser(sysDataVersion.getCreateUser());
        SUser sUser = CreateGson.createGson().fromJson(userJson, SUser.class);

        if(!PlatformSessionContext.getUserID().equals(sysDataVersion.getCreateUser())){
            throw new RuntimeException("覆盖失败，只能覆盖自己创建的版本数据");
        }
        //删除被替换的版本信息
        sysDataVersionRepository.realDelByVersionCode(sysDataVersion.getVersionCode());
        sysDataVersion.setDelFlag(YNEnum.N.toString());
        sysDataVersion.setId(IdUtil.simpleUUID());
        sysDataVersion.setUploadTime(PlatformDateUtils.getCurrentTimestamp());
        sysDataVersion.setIsSpatialData(1);
        sysDataVersion.setSpatialDataType(3);
        sysDataVersion.setUploadUser(sUser.getUserId());
        sysDataVersion.setCreateTime(new Date());
        sysDataVersion.setCreateUser(sUser.getUserId());
        sysDataVersion.setUploadUserName(sUser.getUserName());
        Integer dataRangeCountry = sysDataVersion.getDataRangeCountry();
        StringBuilder areaId = new StringBuilder("");
        if (PlatformObjectUtils.isNotEmpty(sysDataVersion.getDataRangeProvince()) && !"全国".equals(sysDataVersion.getDataRangeProvince())) {
            areaId.append(sysDataVersion.getDataRangeProvince());
        }
        if (PlatformObjectUtils.isNotEmpty(sysDataVersion.getDataRangeCity()) && !"全部".equals(sysDataVersion.getDataRangeCity())) {
            areaId.append(",").append(sysDataVersion.getDataRangeCity());
        }
        if (PlatformObjectUtils.isNotEmpty(sysDataVersion.getDataRangeArea()) && !"全部".equals(sysDataVersion.getDataRangeArea())) {
            areaId.append(",").append(sysDataVersion.getDataRangeArea());
        }
        String areaName = "";
        if (StringUtils.isNotBlank(areaId.toString())) {
            areaName = sysAreaService.getAreaNameByAreaId(areaId.toString());
        }
        sysDataVersion.setDataRangeStr(getDataRanageStr(areaName, dataRangeCountry).toString());
        //保存新的版本信息
        sysDataVersionRepository.save(sysDataVersion);
        //删除旧的关联数据
        String typeCode = sysDataVersion.getDataTypeLevel2();
        if (typeCode.equals(FxfzConstants.HPYGYX)) {
            //删除之前关联的版本信息数据
            sensingImageService.deleteByVersion(sysDataVersion.getVersionCode());
            //用正确的版本号替换之前的临时版本号
            sensingImageService.updateLs(sysDataVersion.getVersionCode(), sysDataVersion.getTempVersionCode());
        }
        if (typeCode.equals(FxfzConstants.DM)) {
            //删除之前关联的版本信息数据
            landformService.deleteByVersion(sysDataVersion.getVersionCode());
            //用正确的版本号替换之前的临时版本号
            landformService.updateLs(sysDataVersion.getVersionCode(), sysDataVersion.getTempVersionCode());
        }
        if (typeCode.equals(FxfzConstants.TRMD)) {
            //删除之前关联的版本信息数据
            naturalDensityService.deleteByVersion(sysDataVersion.getVersionCode());
            //用正确的版本号替换之前的临时版本号
            naturalDensityService.updateLs(sysDataVersion.getVersionCode(), sysDataVersion.getTempVersionCode());
        }
        if (typeCode.equals(FxfzConstants.BELT)) {
            //删除之前关联的版本信息数据
            seismotectionService.deleteBeltByVersion(sysDataVersion.getVersionCode());
            //用正确的版本号替换之前的临时版本号
            seismotectionService.updateBeltLs(sysDataVersion.getVersionCode(), sysDataVersion.getTempVersionCode());

        }
        if (typeCode.equals(FxfzConstants.ZONE)) {
            //删除之前关联的版本信息数据
            seismotectionService.deleteZoneByVersion(sysDataVersion.getVersionCode());
            //用正确的版本号替换之前的临时版本号
            seismotectionService.updateZoneLs(sysDataVersion.getVersionCode(), sysDataVersion.getTempVersionCode());

        }
        return sysDataVersion.getVersionCode();
    }

    @Transactional(rollbackFor = Exception.class)
    public void delByIds(List<String> ids) throws Exception{
        String currUserId = PlatformSessionContext.getUserID();
        List<SysDataVersion> sysDataVersions = sysDataVersionRepository.selectByIds(ids);
        for (SysDataVersion sysDataVersion : sysDataVersions) {
            if(!currUserId.equals(sysDataVersion.getCreateUser())){
                throw new RuntimeException("删除失败，只能删除自己上传的数据");
            }
            delBizDataByVersionCode(sysDataVersion);
        }
        sysDataVersionRepository.delByIds(ids, currUserId, new Date());
    }

    /**
     * 根据数据版本删除业务数据
     *
     * @param sysDataVersion 数据版本信息
     */
    private void delBizDataByVersionCode(SysDataVersion sysDataVersion) {
        String dataTypeLevel2 = sysDataVersion.getDataTypeLevel2();
        if (dataTypeLevel2.equals(FxfzConstants.HPYGYX)) {
            //删除之前关联的版本信息数据
            sensingImageService.deleteByVersion(sysDataVersion.getVersionCode());
        }
        if (dataTypeLevel2.equals(FxfzConstants.DM)) {
            //删除之前关联的版本信息数据
            landformService.deleteByVersion(sysDataVersion.getVersionCode());
        }
        if (dataTypeLevel2.equals(FxfzConstants.TRMD)) {
            //删除之前关联的版本信息数据
            naturalDensityService.deleteByVersion(sysDataVersion.getVersionCode());
        }
        if (dataTypeLevel2.equals(FxfzConstants.BELT)) {
            //删除之前关联的版本信息数据
            seismotectionService.deleteBeltByVersion(sysDataVersion.getVersionCode());
        }
        if (dataTypeLevel2.equals(FxfzConstants.ZONE)) {
            //删除之前关联的版本信息数据
            seismotectionService.deleteZoneByVersion(sysDataVersion.getVersionCode());
        }
    }

    public PageResult<SysDataVersionPageVo> page(SysDataVersionPageParam sysDataVersionPageParam) {
        int tPNum = sysDataVersionPageParam.getPage();
        sysDataVersionPageParam.setPage(sysDataVersionPageParam.getRows() * (Math.max(sysDataVersionPageParam.getPage(), 1) - 1));
        // 构建上传人用户名查询
        if (StringUtils.isNotBlank(sysDataVersionPageParam.getUploadUsername())) {
            sysDataVersionPageParam.setUploadUserIds(StringUtils.join(getLikeUsernameUploadUserId(sysDataVersionPageParam.getUploadUsername()), "','"));
        }
        List<SysDataVersion> list = sysDataVersionRepository.page(sysDataVersionPageParam);
        List<SysDataVersionPageVo> restList = new ArrayList<>();
        for (SysDataVersion sysDataVersion : list) {
            SysDataVersionPageVo sysDataVersionPageVo = new SysDataVersionPageVo() {{
                setId(sysDataVersion.getId());
                setVersionCode(sysDataVersion.getVersionCode());
                setVersionTime(sysDataVersion.getVersionTime());
                setVersionDesc(sysDataVersion.getVersionDesc());
                setUploadUserId(sysDataVersion.getUploadUser());
                setUploadUser(getUser(sysDataVersion.getUploadUser()).getUserName());
                setUploadTime(sysDataVersion.getUploadTime());
                setUpdateDesc(sysDataVersion.getUpdateDesc());
                setDataName(sysDataVersion.getDataName());
                setDataDesc(sysDataVersion.getDataDesc());
                setDataRange(sysDataVersion.getDataRangeStr());

            }};
            if (StringUtils.isNotBlank(sysDataVersion.getDataFileIds())) {
                String[] dataFileIds = sysDataVersion.getDataFileIds().split(",");
                List<SysDataVersionPageVo.DataFile> dataFileList = new ArrayList<>();
                for (String dataFileId : dataFileIds) {
                    AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileId);
                    if (null != attach) {
                        SysDataVersionPageVo.DataFile dataFile = new SysDataVersionPageVo.DataFile();
                        dataFile.setId(attach.getAttachId());
                        dataFile.setName(attach.getAttachName());
                        dataFileList.add(dataFile);
                    }
                    sysDataVersionPageVo.setDataFileList(dataFileList);
                }
            }
            if (StringUtils.isNotBlank(sysDataVersion.getAttachmentIds())) {
                String[] attachIds = sysDataVersion.getAttachmentIds().split(",");
                List<SysDataVersionPageVo.Attachment> attachmentList = new ArrayList<>();
                for (String dataFileId : attachIds) {
                    AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileId);
                    if (null != attach) {
                        SysDataVersionPageVo.Attachment attachment = new SysDataVersionPageVo.Attachment();
                        attachment.setId(attach.getAttachId());
                        attachment.setName(attach.getAttachName());
                        attachmentList.add(attachment);
                    }
                    sysDataVersionPageVo.setAttachmentList(attachmentList);
                }
            }
            restList.add(sysDataVersionPageVo);
        }
        Integer total = sysDataVersionRepository.countForPage(sysDataVersionPageParam);
        return new PageResult<>(tPNum, sysDataVersionPageParam.getRows(), PageUtil.totalPage(total, sysDataVersionPageParam.getRows()), total, restList);
    }

    private List<String> getLikeUsernameUploadUserId(String username) {
        String redisKey = RedisKeyConstants.SYS_USER_INFO_KEY;
        List<String> userCache = stringRedisTemplate.opsForList().range(redisKey, 0, stringRedisTemplate.opsForList().size(redisKey));
        List<String> likeUserIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(userCache)) {
            for (String userStr : userCache) {
                SUser sUser = CreateGson.createGson().fromJson(userStr, SUser.class);
                if (sUser.getUserName().contains(username)) {
                    likeUserIds.add(sUser.getUserId());
                }
            }
        }
        if (CollectionUtils.isEmpty(likeUserIds)) {
            List<String> userIdList = sysDataVersionRepository.selectAllUploadUserId();
            for (String userId : userIdList) {
                SUser user = this.getUser(userId);
                if (user.getUserName().contains(username)) {
                    likeUserIds.add(user.getUserId());
                }
            }
            if (likeUserIds.isEmpty()) {
                likeUserIds.add(UUID.randomUUID().toString());
            }
        }
        return likeUserIds;

    }

    /**
     * 获取用户信息
     * <p>
     * 用户id
     * 先走缓存，缓存没有调接口，然后存储缓存，配置缓存60分钟过期
     */
    public SUser getUser(String userId) {
        String redisKey = RedisKeyConstants.SYS_USER_INFO_KEY;
        List<String> userCache = stringRedisTemplate.opsForList().range(redisKey, 0, stringRedisTemplate.opsForList().size(redisKey));
        if (!CollectionUtils.isEmpty(userCache)) {
            for (String userStr : userCache) {
                SUser sUser = CreateGson.createGson().fromJson(userStr, SUser.class);
                if (sUser.getUserId().equals(userId)) {
                    return sUser;
                }
            }
        }
        String userJson = sUserService.getSUser(userId);
        if (StringUtils.isBlank(userJson)) {
            throw new NullPointerException();
        }
        stringRedisTemplate.opsForList().rightPush(redisKey, userJson);
        stringRedisTemplate.expire(redisKey, 60, TimeUnit.MINUTES);
        return CreateGson.createGson().fromJson(userJson, SUser.class);

    }

    public List<SysDataVersionPageVo> list(SysDataVersionPageParam sysDataVersionPageParam) {
        sysDataVersionPageParam.setRows(null);
        sysDataVersionPageParam.setPage(null);
        List<SysDataVersion> list = sysDataVersionRepository.page(sysDataVersionPageParam);
        List<SysDataVersionPageVo> restList = new ArrayList<>();
        for (SysDataVersion sysDataVersion : list) {
            SysDataVersionPageVo sysDataVersionPageVo = new SysDataVersionPageVo() {{
                setId(sysDataVersion.getId());
                setVersionCode(sysDataVersion.getVersionCode());
                setVersionTime(sysDataVersion.getVersionTime());
                setVersionDesc(sysDataVersion.getVersionDesc());
                setUploadUserId(sysDataVersion.getUploadUser());
                setUploadUser(getUser(sysDataVersion.getUploadUser()).getUserName());
                setUploadTime(sysDataVersion.getUploadTime());
                setUpdateDesc(sysDataVersion.getUpdateDesc());
                setDataName(sysDataVersion.getDataName());
                setDataDesc(sysDataVersion.getDataDesc());
                setDataRange(sysDataVersion.getDataRangeStr());
            }};
            if (StringUtils.isNotBlank(sysDataVersion.getDataFileIds())) {
                String[] dataFileIds = sysDataVersion.getDataFileIds().split(",");
                List<SysDataVersionPageVo.DataFile> dataFileList = new ArrayList<>();
                for (String dataFileId : dataFileIds) {
                    AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileId);
                    if (attach != null) {
                        SysDataVersionPageVo.DataFile dataFile = new SysDataVersionPageVo.DataFile();
                        dataFile.setId(attach.getAttachId());
                        dataFile.setName(attach.getAttachName());
                        dataFileList.add(dataFile);
                    }
                    sysDataVersionPageVo.setDataFileList(dataFileList);
                }
            }
            if (StringUtils.isNotBlank(sysDataVersion.getAttachmentIds())) {
                String[] attachIds = sysDataVersion.getAttachmentIds().split(",");
                List<SysDataVersionPageVo.Attachment> attachmentList = new ArrayList<>();
                for (String dataFileId : attachIds) {
                    AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileId);
                    if (attach != null) {
                        SysDataVersionPageVo.Attachment attachment = new SysDataVersionPageVo.Attachment();
                        attachment.setId(attach.getAttachId());
                        attachment.setName(attach.getAttachName());
                        attachmentList.add(attachment);
                    }
                    sysDataVersionPageVo.setAttachmentList(attachmentList);
                }
            }
            restList.add(sysDataVersionPageVo);
        }
        return restList;
    }

    /**
     * 检查空间文件的完整性
     *
     * @param fileIds
     * @return
     */
    public boolean shpFileAllHasCheck(String fileIds) {
        String[] split = fileIds.split(",");
        Map<String, Boolean> map = new HashMap<>();
        map.put("shp", false);
        map.put("prj", false);
        map.put("dbf", false);
        map.put("cpg", false);
        map.put("shx", false);
        for (String id : split) {
            AttachmentInfoEntity attach = attachmentInfoService.getAttach(id);
            String suffix = FileUtil.getSuffix(attach.getAttachName());
            if (map.get(suffix) != null) {
                map.put(suffix, true);
            }
        }
        for (Boolean value : map.values()) {
            if (!value) {
                return false;
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public RestResponse parseShp(String fileIds, String typeCode) throws Exception {
        if (!shpFileAllHasCheck(fileIds)) {
            return RestResponse.fail("shp,cpg,dbf,prj,shx未全部上传或者正在上传中，请上传完成后再继续!");
        }
        this.uniformFileName(fileIds);
        ParsingResult shpData = getShpData(fileIds);
        //是否成功
        if (!shpData.getMessage().equals("ok")) {
            return RestResponse.fail(shpData.getMessage());
        }
        return saveShpTemporaryData(shpData, typeCode);
    }

    /**
     * 保存解析的数据
     */
    private RestResponse saveShpTemporaryData(ParsingResult shpData, String typeCode) {
        try {
            if (typeCode.equals(FxfzConstants.HPYGYX)) {
                return sensingImageService.saveShpTemporaryData(shpData);
            } else if (typeCode.equals(FxfzConstants.DM)) {
                return landformService.saveShpTemporaryData(shpData);
            } else if (typeCode.equals(FxfzConstants.TRMD)) {
                return naturalDensityService.saveShpTemporaryData(shpData);
            } else if (typeCode.equals(FxfzConstants.BELT) || typeCode.equals(FxfzConstants.ZONE)) {
                return seismotectionService.saveShpTemporaryData(shpData, typeCode);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return RestResponse.fail("该数据类别下没有shp数据");
        }
        return null;
    }

    /**
     * 统一文件名
     *
     * @param fileIds
     */
    private void uniformFileName(String fileIds) {
        String[] idList = fileIds.split(",");
        AttachmentInfoEntity attachRoot = attachmentInfoService.getAttach(idList[0]);
        String attachRootPath = attachRoot.getAttachPath();
        String filePathCurrTime = getFilePathCurrTime(attachRootPath);
        for (int i = 1; i < idList.length; i++) {
            AttachmentInfoEntity attach = attachmentInfoService.getAttach(idList[i]);
            if (getFilePathCurrTime(attach.getAttachPath()).equals(filePathCurrTime)) {
                continue;
            }
            String attachPath = attach.getAttachPath();
            String fileDiskPath = localDir + attachPath;
//            FileUtil.rename(new File(fileDiskPath), getNonSuffixFileName(attach.getAttachName()) + "_" + filePathCurrTime + "." + FileUtil.getSuffix(attach.getAttachName()), true);
//            String[] s = attachPath.split("_");
//            attach.setAttachPath(s[0] + "_" + filePathCurrTime + "." + FileUtil.getSuffix(attach.getAttachName()));
//            attachmentInfoService.update(attach);
//            String newName = getNonSuffixFileName(attach.getAttachName()) + "_" + filePathCurrTime + "." + FileUtil.getSuffix(attach.getAttachName());
            String attachName = attach.getAttachName();
            attachName = attachName.substring(0, attachName.lastIndexOf("_"));
            String newName = attachName + "_" + filePathCurrTime + "." + FileUtil.getSuffix(attach.getAttachName());
            FileUtil.rename(new File(fileDiskPath), newName, true);
            attach.setAttachPath(attachPath.replace(getFilePathCurrTime(attachPath), filePathCurrTime));
            attachmentInfoService.update(attach);
        }
    }

    private String getNonSuffixFileName(String fileName) {
        return fileName.replaceAll("." + FileUtil.getSuffix(fileName), "");
    }

    private String getFilePathCurrTime(String filePath) {
        return filePath.split("_")[1].replaceAll("." + FileUtil.getSuffix(filePath.split("_")[1]), "");
    }

    public ParsingResult getShpData(String fileIds) throws Exception {
        //.prj结尾用来校验是否为2000坐标系
        String prj = "";
        //.cpg文件用来获得编码格式,例如utf-8
        String cpg = "";
        //.shp文件用来获得数据
        String shp = "";
        //根据id获取真实地址
        String[] split = fileIds.split(",");
        for (String id : split) {
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(id);
            String attachPath = attachmentInfoEntity.getAttachPath();
            String substring = attachPath.substring(attachPath.length() - 4);

            if (substring.equals(".prj")) {
                prj = localDir + File.separator + attachPath;
            } else if (substring.equals(".cpg")) {
                cpg = localDir + File.separator + attachPath;
            } else if (substring.equals(".shp")) {
                shp = localDir + File.separator + attachPath;
            }
        }
        return ShpAnalyticUtil.analytic(prj, cpg, shp);
    }

    public List<SysDataVersion> getDataVersionView(SysDataVersionPageParam sysDataVersionPageParam) {
        return sysDataVersionRepository.getDataVersionView(sysDataVersionPageParam);
    }

    public Map<String, Object> sameTypeDataExist(SysDataVersionSameTypeDataExistParam sysDataVersionSameTypeDataExistParam) {
        String versionCode = sysDataVersionRepository.sameTypeDataExist(sysDataVersionSameTypeDataExistParam);
        boolean isExist = StringUtils.isNotBlank(versionCode);
        return new HashMap<String, Object>() {
            {
                put("isExist", isExist);
                if (isExist) {
                    put("tipMsg", "本系统已有同类数据（版本号为" + versionCode + "），是否作为新版本数据进行上传？");
                    put("versionCode", versionCode);
                }
            }
        };
    }

    /**
     * 获取版本列表   dataType 为1时 是获取 地形地貌坡度  为2时 是获取地形地貌坡向
     * 为3时 是获取滑坡遥感影像解译数据 为4时 是获取地貌数据 为5时 是获取天然密度数据
     */
    public List<SysDataVersion> getVersionInfo(SysDataVersionPageParam param, String geom) {
        return sysDataVersionRepository.getVersionInfo(param, geom);
    }

    public Map<String, Object> getPage(PageQueryParam queryParams) {
        StringBuilder str = new StringBuilder("");
        StringBuilder sql = new StringBuilder(" select  c.id,c.version_code,c.version_time,c.data_range_str,c.upload_user_name,c.upload_time" +
                ",'" + queryParams.getDataTypeLevel3() + "' as dataTypeLevel3 from dzzh_sys_data_version c ");
        StringBuilder whereSql = new StringBuilder(" where c.del_flag = '" + YNEnum.N.toString() + "'");
        if (!PlatformObjectUtils.isEmpty(queryParams.getDataTypeLevel3())) {
            if ("4".equals(queryParams.getDataTypeLevel3())){
                whereSql.append(" and c.data_type_level2 = '").append("dm").append("'");
            }else if ("5".equals(queryParams.getDataTypeLevel3())) {
                whereSql.append(" and c.data_type_level2 = '").append("trmd").append("'");
            }
        }
        if (!PlatformObjectUtils.isEmpty(queryParams.getVersionDesc())) {
            whereSql.append(" and c.version_desc like '%").append(queryParams.getVersionDesc()).append("%'");
        }
        if (!PlatformObjectUtils.isEmpty(queryParams.getUploadUsername())) {
            whereSql.append(" and c.upload_user_name like '%").append(queryParams.getUploadUsername()).append("%'");
        }
        if (queryParams.getUploadStartTime() != null && queryParams.getUploadEndTime() != null) {
            whereSql.append("and c.upload_time between '").append(DateUtil.format(queryParams.getUploadStartTime(), "yyyy-MM-dd")).append("' and '").append(DateUtil.format(queryParams.getUploadEndTime(), "yyyy-MM-dd")).append("' ");
        }
        sql.append(whereSql).append(" order by c.upload_time").toString();
        int firstIndex = (queryParams.getPage() - 1) * queryParams.getRows();
        int lastIndex = queryParams.getRows();
        StringBuilder limitSql = new StringBuilder(" limit " + lastIndex + " offset " + firstIndex);
        Integer total = jdbcTemplate.query(sql.toString(), new BeanPropertyRowMapper<>(VersionVO.class)).size();
        List<SysDataVersion> versionEntities = jdbcTemplate.query(sql.append(limitSql).toString(), new BeanPropertyRowMapper<>(SysDataVersion.class));
        if (PlatformObjectUtils.isNotEmpty(versionEntities)) {
            versionEntities.forEach(version -> {
                version.setDataRange(version.getDataRangeStr());
                version.setUploadUser(version.getUploadUserName());
            });
        }
        Map<String, Object> map = new HashMap<>();
        map.put("rows", versionEntities);
        map.put("total", total);
        return map;
    }

    public DictItemTreeNodeVo getDataTypeLevel1AndDataTypeLevel2Tree(String dictCode) {
        DictItemTreeNodeVo vo = new DictItemTreeNodeVo();
        DictEntity dictEntity = dictRepository.findOneByDictCode(dictCode);
        if (PlatformObjectUtils.isNotEmpty(dictCode)) {
            vo.setDictId(dictEntity.getDictId());
            vo.setDictCode(dictEntity.getDictCode());
            vo.setDictName(dictEntity.getDictName());
            List<DictItemEntity> dictItemList = dictItemRepository.findDictItemsByDictCode(dictCode);
            if (PlatformObjectUtils.isNotEmpty(dictItemList)) {
                vo.setChildren(dictItemList);
            }
        }
        return vo;
    }

    public RestResponse getFileDesc(String typeCode2) {
        List<FieldDesc> list = new ArrayList<>();
        if (typeCode2.equals(FxfzConstants.HPYGYX)) {
            list = sensingImageService.getFieldDesc();
        }
        //地貌业务数据
        if (typeCode2.equals(FxfzConstants.DM)) {
            list = landformService.getFieldDesc();
        }
        //天然密度数据
        if (typeCode2.equals(FxfzConstants.TRMD)) {
            list = naturalDensityService.getFieldDesc();
        }
        //地震构造-地震带
        if (typeCode2.equals(FxfzConstants.BELT)) {
            list = seismotectionService.getBeltFieldDesc();
        }
        //地震构造-地震构造区
        if (typeCode2.equals(FxfzConstants.ZONE)) {
            list = seismotectionService.getZoneFieldDesc();
        }
        return ResponseCreator.createSuccessResponse(list);
    }

    public List<SysDataVersion> getVersionList(Map<String, Object> map) {
        return sysDataVersionRepository.getVersionList(map);
    }

    public SysDataVersionFileVO getFileMessage(String versionCode) {
        SysDataVersion sysDataVersion = sysDataVersionRepository.getByVersionCode(versionCode);
        if(sysDataVersion==null){
            return null;
        }
        SysDataVersionFileVO vo = new SysDataVersionFileVO();
        if (StringUtils.isNotBlank(sysDataVersion.getDataFileIds())) {
            String[] dataFileIds = sysDataVersion.getDataFileIds().split(",");
            List<AttachmentInfoEntity> dataFileList = new ArrayList<>();
            for (String dataFileId : dataFileIds) {
                AttachmentInfoEntity DataFile = attachmentInfoService.getAttach(dataFileId);
                dataFileList.add(DataFile);
            }
            if (dataFileList.size() > 0) {
                vo.setDataFileList(dataFileList);
            }
        }
        if (StringUtils.isNotBlank(sysDataVersion.getAttachmentIds())) {
            String[] attachIds = sysDataVersion.getAttachmentIds().split(",");
            List<AttachmentInfoEntity> attachmentList = new ArrayList<>();
            for (String dataFileId : attachIds) {
                AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileId);
                attachmentList.add(attach);
            }
            if (attachmentList.size() > 0) {
                vo.setAttachmentFileList(attachmentList);
            }
        }
        return vo;
    }

    public Map<String, Object> getYwDetails(String typeCode, String id) {
        Map<String, Object> map = new HashMap<>();
        if (typeCode.equals(FxfzConstants.HPYGYX)) {
            SensingImage sensingImage = sensingImageService.getYwDetails(id);
            map.put("title", sensingImageService.getFieldTable());
            map.put("data", sensingImage);
        }
        //地貌业务数据
        if (typeCode.equals(FxfzConstants.DM)) {
            LandForm landForm = landformService.getYwDetails(id);
            map.put("title", landformService.getFieldTable());
            map.put("data", landForm);
        }
        //天然密度数据
        if (typeCode.equals(FxfzConstants.TRMD)) {
            NaturalDensity naturalDensity = naturalDensityService.getYwDetails(id);
            map.put("title", naturalDensityService.getFieldTable());
            map.put("data", naturalDensity);
        }
        //地震构造-地震带
        if (typeCode.equals(FxfzConstants.BELT)) {
            SeismotectionBelt seismotectionBelt = seismotectionService.getYwBeltDetails(id);
            map.put("title", seismotectionService.getBeltFieldTable());
            map.put("data", seismotectionBelt);
        }
        //地震构造-地震构造区
        if (typeCode.equals(FxfzConstants.ZONE)) {
            SeismotectionZone seismotectionZone = seismotectionService.getYwZoneDetails(id);
            map.put("title", seismotectionService.getZoneFieldTable());
            map.put("data", seismotectionZone);
        }
        return map;
    }


    public Map<String, Object> getYwVesrionData(PageQueryParam pageQueryParam) {
        Map<String, Object> ywVesrionData = sysDataVersionRepository.getYwVesrionData(pageQueryParam);
        List<VersionVO> list = (List<VersionVO>) ywVesrionData.get("rows");
        if (PlatformObjectUtils.isNotEmpty(list) && list.size() > 0) {
            list.forEach(vo -> {
//                if("dxdmpd".equals(pageQueryParam.getDataTypeLevel3())){
//                    vo.setDataTypeLevel3("6");
//                }else if ("dm".equals(pageQueryParam.getDataTypeLevel3())) {//地貌数据
//                    vo.setDataTypeLevel3("7");
//                }else if ("trmd".equals(pageQueryParam.getDataTypeLevel3())) {//天然密度数据
//                    vo.setDataTypeLevel3("8");
//                }
//                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//                Date versionTime = vo.getVersionTime();
//                String format = simpleDateFormat.format(versionTime);
//                vo.setVersionTime(simpleDateFormat.parse(format));
                if (StringUtils.isNotBlank(vo.getDataFileIds())) {
                    String[] dataFileIds = vo.getDataFileIds().split(",");
                    List<AttachmentInfoEntity> dataFileList = new ArrayList<>();
                    for (String dataFileId : dataFileIds) {
                        AttachmentInfoEntity DataFile = attachmentInfoService.getAttach(dataFileId);
                        dataFileList.add(DataFile);
                    }
                    if (dataFileList.size() > 0) {
                        vo.setDataFileList(dataFileList);
                    }
                }
                if (StringUtils.isNotBlank(vo.getAttachmentIds())) {
                    String[] attachIds = vo.getAttachmentIds().split(",");
                    List<AttachmentInfoEntity> attachmentList = new ArrayList<>();
                    for (String dataFileId : attachIds) {
                        AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileId);
                        attachmentList.add(attach);
                    }
                    if (attachmentList.size() > 0) {
                        vo.setAttachmentFileList(attachmentList);
                    }
                }
            });
        }
        return ywVesrionData;
    }

    public JSONObject getFilePathByVersion(String versionCode) {
        SysDataVersion sysDataVersion = sysDataVersionRepository.getByVersionCode(versionCode);
        if (sysDataVersion == null) {
            return null;
        }
        String dataFileIds = sysDataVersion.getDataFileIds();
        if (StringUtils.isBlank(dataFileIds)) {
            return null;
        }
        AttachmentInfoEntity attach = attachmentInfoService.getAttach(dataFileIds);
        if (attach == null) {
            return null;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("filePath", localDir + File.separator + attach.getAttachPath());
        return jsonObject;
    }
}
